﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using GeoAPI.Geometries;
using GeoAPI.Geometries.Prepared;
using NetTopologySuite.Algorithm;
using NetTopologySuite.Geometries.Utilities;

namespace NetTopologySuite.Geometries.Prepared
{
	public class BasicPreparedGeometry : IPreparedGeometry
	{
		public BasicPreparedGeometry(IGeometry geom)
		{
			this._baseGeom = geom;
			this._representativePts = ComponentCoordinateExtracter.GetCoordinates(geom);
		}

		public IGeometry Geometry
		{
			get
			{
				return this._baseGeom;
			}
		}

		public IList<Coordinate> RepresentativePoints
		{
			get
			{
				return new ReadOnlyCollection<Coordinate>(this._representativePts);
			}
		}

		public bool IsAnyTargetComponentInTest(IGeometry testGeom)
		{
			PointLocator pointLocator = new PointLocator();
			foreach (Coordinate p in this.RepresentativePoints)
			{
				if (pointLocator.Intersects(p, testGeom))
				{
					return true;
				}
			}
			return false;
		}

		protected bool EnvelopesIntersect(IGeometry g)
		{
			return this._baseGeom.EnvelopeInternal.Intersects(g.EnvelopeInternal);
		}

		protected bool EnvelopeCovers(IGeometry g)
		{
			return this._baseGeom.EnvelopeInternal.Covers(g.EnvelopeInternal);
		}

		public virtual bool Contains(IGeometry g)
		{
			return this._baseGeom.Contains(g);
		}

		public virtual bool ContainsProperly(IGeometry g)
		{
			return this._baseGeom.EnvelopeInternal.Contains(g.EnvelopeInternal) && this._baseGeom.Relate(g, "T**FF*FF*");
		}

		public bool CoveredBy(IGeometry g)
		{
			return this._baseGeom.CoveredBy(g);
		}

		public virtual bool Covers(IGeometry g)
		{
			return this._baseGeom.Covers(g);
		}

		public bool Crosses(IGeometry g)
		{
			return this._baseGeom.Crosses(g);
		}

		public bool Disjoint(IGeometry g)
		{
			return !this.Intersects(g);
		}

		public virtual bool Intersects(IGeometry g)
		{
			return this._baseGeom.Intersects(g);
		}

		public bool Overlaps(IGeometry g)
		{
			return this._baseGeom.Overlaps(g);
		}

		public bool Touches(IGeometry g)
		{
			return this._baseGeom.Touches(g);
		}

		public bool Within(IGeometry g)
		{
			return this._baseGeom.Within(g);
		}

		public override string ToString()
		{
			return this._baseGeom.ToString();
		}

		private readonly IGeometry _baseGeom;

		private readonly List<Coordinate> _representativePts;
	}
}
